package com.harboursoftware.xstorage.unit.db.sql

import junit.framework.Assert;

import com.harboursoftware.xstorage.TestDatabaseProvider;
import com.harboursoftware.xstorage.XStorageException 
import com.harboursoftware.xstorage.ac.AccessControlPolicy 
import com.harboursoftware.xstorage.ac.CanonicalUserGrantee 
import com.harboursoftware.xstorage.ac.Grant 
import com.harboursoftware.xstorage.ac.GroupGrantee;
import com.harboursoftware.xstorage.ac.Permission 
import com.harboursoftware.xstorage.db.sql.BucketSqlDao 
import com.harboursoftware.xstorage.db.sql.DatabaseProviderImpl 
import com.harboursoftware.xstorage.db.sql.UserSqlDao 
import com.harboursoftware.xstorage.model.XUser 
import com.harboursoftware.xstorage.model.XBucket
import groovy.sql.Sql 

import org.junit.After;
import org.junit.Before;
import org.junit.Test 

class BucketSqlDaoTest {
    def databaseProvider = new TestDatabaseProvider()
    BucketSqlDao bucketDao = new BucketSqlDao(databaseProvider)
    UserSqlDao userDao = new UserSqlDao(databaseProvider)
    def bucketName = 'testbucket'
    
    
    def jdbcUrl = DatabaseProviderImpl.jdbcUrl
    def jdbcUsername = DatabaseProviderImpl.jdbcUsername
    def jdbcPassword = DatabaseProviderImpl.jdbcPassword
    def sqlRunner = Sql.newInstance(jdbcUrl, jdbcUsername, jdbcPassword)

    
    @Before
    void setUp() {
        databaseProvider.recreateDatabase()
    }
    
    @After
    void tearDown() {
        bucketDao = null;
    }
    
    @Test
    void test_saveBucket() {
        def owner = createTestUser()
        def bucket = createTestBucket(owner)
        
        def persistentedBucket =  bucketDao.findBucketByName(bucketName)
        assert persistentedBucket.creationDate != null
        persistentedBucket.creationDate = null
        
        assert bucket == persistentedBucket
        assert countBucketsAtDatabase() == 1
    }
    
    /**
     * 当bucket.user不存在时，saveBucket()应该抛出异常
     */
    @Test(expected = XStorageException)
    void test_saveBucket_when_owner_not_exist() {
        def bucket = new XBucket('xfasdfdsfasdsdfa')
        bucketDao.deleteBucket bucket
    }
    
    @Test
    void test_delete_bucket() {
        def owner = createTestUser()
        def bucket = createTestBucket(owner)
        bucketDao.deleteBucket bucket
        
       assert bucketDao.findBucketByName(bucketName) == null
       assert countBucketsAtDatabase() == 0
    }
    
    /**
     * 删除user时，该user的所有bucket应该也被删除
     */
    void test_findBucket_when_after_delete_owner() {
        //TODO:未完成
    }
    
    void test_upadeBucket() {
        
        
        //TODO:未完成
    }
    
    void test_updateBucket_when_bucket_does_not_exists() {
        //TODO:未完成
    }
    
    /**
     * saveBucekt()时，如果同名的bucket已经存在应该抛出异常
     */
    @Test(expected = XStorageException)
    void save_bucket_when_the_buchet_with_same_name_already_exists() {
        def owner = createTestUser()
        createTestBucket(owner)
        createTestBucket(owner)
    }
    
    private createTestBucket(owner) {
        def ownerGrantee = new CanonicalUserGrantee(owner.id, owner.displayName)
        def ownerFullControl = new Grant(ownerGrantee, Permission.FULL_CONTROL)
        def allUserCanRead = new Grant(GroupGrantee.ALL_USERS, Permission.READ)
        def grants = [ownerFullControl, allUserCanRead]
        def acp = new AccessControlPolicy(owner, grants)
        def bucket = new XBucket(bucketName, owner, acp)
        
        bucketDao.saveBucket bucket
        
        return bucket;
    }
    
    
    private createTestUser() {
        def accessKeyId = '0PN5J17HBGZHT7JJ3X82'
        def secretAccessKey = 'uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o'
        def email = 'test@harboursoftware.com'
        def user = new XUser(null, accessKeyId, secretAccessKey, email, email)
        userDao.saveUser user
        user = userDao.findUserByAccessKeyId(accessKeyId)
        return user
    }
    
    private int countBucketsAtDatabase() {
        def sql = "SELECT * FROM x_bucket WHERE name='${bucketName}'";
        return sqlRunner.rows(sql).size()
    }
    
    
    @Test(expected = XStorageException.class)
    void test_deleteBucket_when_bucket_does_not_exists() {
        def bucket = new XBucket('asfasdfasdjhasdhfjka')
        bucketDao.deleteBucket(bucket)
    }
}
